package com.tony.business.util.curator;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.TreeCache;
import org.apache.curator.retry.RetryNTimes;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;

import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @author tony
 * @date 2020/3/6 8:36 下午
 */
@Slf4j
@Data
public class CuratorUtil {
    private String host = "127.0.0.1";

    private String port = "2181";

    private int sessionTimeoutMs = 2000;

    private int connectTimeoutMs = 2000;

    private CuratorFramework client;

    public boolean create(String key, String value, CreateMode createMode) throws Exception {
        if (exists(key)) {
            throw new Exception("zookeeper创建对象时key已存在");
        }
        client.create().creatingParentContainersIfNeeded().withMode(createMode).forPath(key, value.getBytes(StandardCharsets.UTF_8));
        log.trace("zookeeper创建对象 key：" + key + "\tvalue：" + value + "\t创建模式" + createMode);
        return true;
    }

    public String get(String key) throws Exception {
        byte[] bytes = client.getData().forPath(key);
        return new String(bytes, StandardCharsets.UTF_8);
    }

    public List<String> getChildrensKey(String key) throws Exception {
        if (exists(key)) {
            throw new Exception("zookeeper获取子节点时key不存在");
        }
        return client.getChildren().forPath(key);
    }

    public boolean update(String key, String value) throws Exception {
        if (exists(key)) {
            throw new Exception("zookeeper修改对象时key不存在");
        }
        client.setData().forPath(key, value.getBytes(StandardCharsets.UTF_8));
        log.trace("zookeeper修改对象 key：" + key + "\tvalue：" + value);
        return true;
    }

    public boolean exists(String key) throws Exception {
        Stat stat = client.checkExists().forPath(key);
        if (stat == null) {
            return false;
        }
        log.trace("zookeeper对象判断存在 key：" + key);
        return true;
    }

    public boolean delete(String key) throws Exception {
        client.delete().deletingChildrenIfNeeded().forPath(key);
        log.trace("zookeeper对象删除 key：" + key);
        return true;
    }

    public void subscribe(String key, CuratorSubscribe subscribe) {
        TreeCache treeCache = new TreeCache(client, key);
        try {
            treeCache.start();
            treeCache.getListenable().addListener(subscribe::listener);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void unsubscribe(String key) {
        TreeCache treeCache = new TreeCache(client, key);
        treeCache.close();
    }


    ///////////////////////////////////////////////////////////////////////////
    // 私有方法
    ///////////////////////////////////////////////////////////////////////////

    private void connect() {
        String connectionString = host + ":" + port;
        client = CuratorFrameworkFactory.newClient(connectionString, sessionTimeoutMs,
                connectTimeoutMs, new RetryNTimes(Integer.MAX_VALUE, 1000));
        client.start();
    }

    private void init() {
        connect();
    }

    private void close() {
        if (client != null) {
            client.close();
        }
    }

    public CuratorUtil() {

    }

    ///////////////////////////////////////////////////////////////////////////
    // 工厂方法
    ///////////////////////////////////////////////////////////////////////////

    /*public static CuratorUtil getInstance(){
        if(curatorUtil == null){
            synchronized (CuratorUtil.class){
                if(curatorUtil == null){
                    curatorUtil = new CuratorUtil();
                }
            }
        }
        return curatorUtil;
    }*/
}
